package org.orbroker

import org.orbroker.exception._
import org.orbroker.conv._
import org.orbroker.adapt.BrokerAdapter
import org.orbroker.callback.ExecutionCallback
import java.sql.{ SQLException, ResultSet, Connection, PreparedStatement }

private[orbroker] trait ModifyStatement extends SQLStatement with GenKeyProducer {

  def execute[K](token: Token[K], timeout: Int, conn: Connection, parms: Map[String, _], genKeyHandler: Option[K ⇒ Unit]): (Int, String, Seq[Any]) = {
    val parsed = statement(parms)
    val ps = parsed.prepareUpdate(conn, genKeyHandler.isDefined)
    try {
      ps.setQueryTimeout(timeout)
      val values = setParms(token, ps, parsed.parmDefs, parms)
      val rowsUpdated = ps.executeUpdate()
      for (kh ← genKeyHandler) handleGeneratedKeys(token, kh, ps.getGeneratedKeys, rowsUpdated)
      (rowsUpdated, parsed.sql, values)
    } finally {
      import JdbcCloser._
      checkWarningsAndClose(ps, callback)
    }
  }

  import scala.collection.mutable.ArrayBuffer

  def executeBatch[G](
    token: Token[G], timeout: Int, conn: Connection, batchParms: (String, Traversable[_]),
    parms: Map[String, _], genKeyHandler: Option[G ⇒ Unit]): (Int, String, Seq[Seq[Any]]) = {
    if (batchParms._2.isEmpty) {
      throw new EmptyBatchException(token.id, batchParms._1)
    }
    val parsed = statement(parms)
    val ps = parsed.prepareUpdate(conn, genKeyHandler.isDefined)
    val batchParmName = batchParms._1
    val batchValues = new ArrayBuffer[Seq[Any]]
    try {
      ps.setQueryTimeout(timeout)
      for (batchParm ← batchParms._2) {
        val allParms = parms + (batchParmName -> batchParm)
        batchValues += setParms(token, ps, parsed.parmDefs, allParms)
        ps.addBatch()
      }
      val rowsUpdated = ps.executeBatch().reduceLeft(_ + _)
      for (kh ← genKeyHandler)
        handleGeneratedKeys(token, kh, ps.getGeneratedKeys, rowsUpdated)
      (rowsUpdated, parsed.sql, batchValues)
    } finally {
      import JdbcCloser._
      checkWarningsAndClose(ps, callback)
    }
  }

}
